﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;
using System.Text;

namespace nwrole.lib
{
    public interface IParamService<T>
    {
        void InitParamService(T userData);
    }

    public class ParamServiceInstanceProvider<T> : IInstanceProvider
    {
        private T userData;

        public ParamServiceInstanceProvider(T userData)
        {
            /*if (!serviceType.GetInterfaces().Contains(typeof(IParamService)))
            {
                throw new Exception("serviceType must implement IParamService");
            }*/
            
            this.userData = userData;
        }

        public object GetInstance(InstanceContext instanceContext, Message message)
        {
            object service = Activator.CreateInstance(instanceContext.Host.Description.ServiceType);
            if (!(service is IParamService<T>))
                throw new Exception("serviceType must implement IParamService");

            ((IParamService<T>)service).InitParamService(userData);

            return service;
        }
        public object GetInstance(InstanceContext instanceContext)
        {
            object service = Activator.CreateInstance(instanceContext.Host.Description.ServiceType);
            if (!(service is IParamService<T>))
                throw new Exception("serviceType must implement IParamService");

            ((IParamService<T>)service).InitParamService(userData);

            return service;
        }
        public void ReleaseInstance(InstanceContext instanceContext, object instance)
        {
        }
    }

    public class ParamServiceBehavior<T> : IServiceBehavior
    {
        private ParamServiceInstanceProvider<T> paramServiceProvider;

        public ParamServiceBehavior(T userData)
        {
            paramServiceProvider = new ParamServiceInstanceProvider<T>(userData);
        }


        public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters) { }
        public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
        {
            foreach (ChannelDispatcher cd in serviceHostBase.ChannelDispatchers)
            {
                foreach (EndpointDispatcher ed in cd.Endpoints)
                {
                    ed.DispatchRuntime.InstanceProvider = this.paramServiceProvider;
                }
            }
        }
        public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) { }
    }   
}
